package acme.bloodtime.dao;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import modelo.IArticuloDO;
import modelo.IVampiroArticuloDAO;
import modelo.IVampiroArticuloDO;
import modelo.IVampiroDO;

import dao.api.DataObject;
import dao.api.Reference;

/**
 * 
 * @author Cesar A. Fuguet T.
 * 
 */
public class VampiroArticuloDAO extends BloodTimeBaseDAO implements IVampiroArticuloDAO {

    public VampiroArticuloDAO() {
        // Empty
    }

    @Override
    public void createTable() throws SQLException {
        StringBuffer strbuf;

        // ----------------------------------------

        strbuf = new StringBuffer();

        // ------------------------------------------------------------------
        // It could be a good practice to implement the method getTableName
        // in BaseDAO and eliminate the DAO part to generalize the method.
        // ------------------------------------------------------------------

        dropTable();

        System.err.println(strbuf.toString());

        connection.createStatement().execute(strbuf.toString());

        // ----------------------------------------

        strbuf = new StringBuffer();

        strbuf.append("CREATE TABLE ");
        strbuf.append(getTableName());
        strbuf.append(" (");
        strbuf.append(VampiroArticuloDO.ID);
        strbuf.append(" SERIAL PRIMARY KEY, ");
        strbuf.append(VampiroArticuloDO.EQUIPADO);
        strbuf.append(" BOOLEAN NOT NULL, ");

        VampiroDAO vampiroDAO = new VampiroDAO();

        strbuf.append(VampiroArticuloDO.VAMPIRO_ID);
        strbuf.append(" INT REFERENCES ");
        strbuf.append(vampiroDAO.getTableName());
        strbuf.append(" NOT NULL, ");

        ArticuloDAO articuloDAO = new ArticuloDAO();

        strbuf.append(VampiroArticuloDO.ARTICULO_ID);
        strbuf.append(" INT REFERENCES ");
        strbuf.append(articuloDAO.getTableName());
        strbuf.append(" NOT NULL, ");

        strbuf.append(" UNIQUE(");
        strbuf.append(VampiroArticuloDO.ARTICULO_ID);
        strbuf.append(" , ");
        strbuf.append(VampiroArticuloDO.VAMPIRO_ID);
        strbuf.append(")");

        strbuf.append(")");

        System.err.println(strbuf.toString());

        connection.createStatement().execute(strbuf.toString());
    }

    @Override
    public void delete(DataObject dataObject) throws SQLException {
        internalDelete(dataObject, VampiroArticuloDO.class);
    }

    @Override
    public void insert(DataObject dataObject) throws SQLException {
        checkCache(dataObject, CHECK_INSERT);
        checkClass(dataObject, VampiroArticuloDO.class, CHECK_INSERT);

        VampiroArticuloDO vampiroArticuloDO = (VampiroArticuloDO) dataObject;

        vampiroArticuloDO.setId(getNextId());

        StringBuffer strbuf = new StringBuffer();

        strbuf.append("INSERT INTO ");
        strbuf.append(getTableName());
        strbuf.append(" VALUES (");
        strbuf.append(vampiroArticuloDO.getId());
        strbuf.append(", ");
        strbuf.append(vampiroArticuloDO.isEquipado());
        strbuf.append(", ");

        // ---------------------------------
        // Setting the Reference to Vampiro
        // ---------------------------------

        Reference<IVampiroDO> vampiroRef = vampiroArticuloDO.getVampiroId();
        vampiroRef.checkInsert();

        strbuf.append(vampiroRef.getIdAsString());
        strbuf.append(", ");

        // ---------------------------------
        // Setting the Reference to Articulo
        // ---------------------------------

        Reference<IArticuloDO> articuloRef = vampiroArticuloDO.getArticuloId();
        articuloRef.checkInsert();

        strbuf.append(articuloRef.getIdAsString());
        strbuf.append(")");

        System.err.println(strbuf.toString());

        connection.createStatement().executeUpdate(strbuf.toString());

        dtaSession.add(dataObject);
    }

    protected IVampiroArticuloDO resultSetToDO(ResultSet rs) throws SQLException {
        VampiroArticuloDO ret = //
        (VampiroArticuloDO) dtaSession.getDtaByKey( //
                VampiroArticuloDO.class, rs.getInt(VampiroArticuloDO.ID));

        if (ret != null) {
            return ret;
        }

        ret = new VampiroArticuloDO();

        ret.setId/*     			*/(rs.getInt(VampiroArticuloDO.ID));
        ret.setEquipado/*			*/(rs.getBoolean(VampiroArticuloDO.EQUIPADO));

        // ----------------------------
        // Setting the reference id's
        // ----------------------------

        Reference<IVampiroDO> vampiroRef = new Reference<IVampiroDO>();
        vampiroRef.setRefIdent(rs.getInt(VampiroArticuloDO.VAMPIRO_ID));

        // ---------------------
        // Vampiro Reference Id
        // ---------------------

        ret.setVampiroId(vampiroRef);

        Reference<IArticuloDO> articuloRef = new Reference<IArticuloDO>();
        articuloRef.setRefIdent(rs.getInt(VampiroArticuloDO.ARTICULO_ID));

        // -----------------------
        // Articulo Reference Id
        // -----------------------

        ret.setArticuloId(articuloRef);

        // -------------------------------------------------------------------

        return (VampiroArticuloDO) dtaSession.add(ret);
    }

    @Override
    public void update(DataObject dataObject) throws SQLException {
        checkCache(dataObject, CHECK_UPDATE);
        checkClass(dataObject, VampiroArticuloDO.class, CHECK_UPDATE);

        VampiroArticuloDO vampiroArticuloDO = (VampiroArticuloDO) dataObject;

        StringBuffer strbuf = new StringBuffer();

        strbuf.append("UPDATE ");
        strbuf.append(getTableName());
        strbuf.append(" SET ");

        strbuf.append(VampiroArticuloDO.EQUIPADO);
        strbuf.append(" = ");
        strbuf.append(vampiroArticuloDO.isEquipado());
        strbuf.append(", ");
        
        // ----------------------------
        // Set Vampiro Reference Id
        // ----------------------------

        Reference<IVampiroDO> vampiroRef = vampiroArticuloDO.getVampiroId();
        vampiroRef.checkUpdate();

        strbuf.append(VampiroArticuloDO.VAMPIRO_ID);
        strbuf.append(" = ");
        strbuf.append(vampiroRef.getIdAsString());
        strbuf.append(", ");
        
        // ----------------------------
        // Set Articulo Reference Id
        // ----------------------------

        Reference<IArticuloDO> articuloRef = vampiroArticuloDO.getArticuloId();
        articuloRef.checkUpdate();

        strbuf.append(VampiroArticuloDO.ARTICULO_ID);
        strbuf.append(" = ");
        strbuf.append(articuloRef.getIdAsString());

        strbuf.append(" WHERE ");
        strbuf.append(VampiroArticuloDO.ID);
        strbuf.append(" = ");
        strbuf.append(vampiroArticuloDO.getId());

        System.err.println(strbuf.toString());

        connection.createStatement().executeUpdate(strbuf.toString());
    }

    public void loadVampiroRef(IVampiroArticuloDO vampiroArticuloDO) throws SQLException {
        checkClass(vampiroArticuloDO, VampiroArticuloDO.class, CHECK_UPDATE);

        VampiroDAO vampiroDAO = new VampiroDAO();
        vampiroDAO.init(connectionBean);

        Reference<IVampiroDO> ref = vampiroArticuloDO.getVampiroId();

        // ----------------------------------------
        // If ident == 0 there is nothing to do
        // ----------------------------------------

        if (ref.getRefIdent() == 0) {
            return;
        }

        IVampiroDO vampiroDO = //
        (IVampiroDO) vampiroDAO.loadById(ref.getRefIdent());

        ref.setRefValue(vampiroDO);
    }

    public void loadArticuloRef(IVampiroArticuloDO vampiroArticuloDO) throws SQLException {
        checkClass(vampiroArticuloDO, VampiroArticuloDO.class, CHECK_UPDATE);

        ArticuloDAO articuloDAO = new ArticuloDAO();
        articuloDAO.init(connectionBean);

        Reference<IArticuloDO> ref = vampiroArticuloDO.getArticuloId();

        // ----------------------------------------
        // If ident == 0 there is nothing to do
        // ----------------------------------------

        if (ref.getRefIdent() == 0) {
            return;
        }

        ArticuloDO articuloDO = //
        (ArticuloDO) articuloDAO.loadById(ref.getRefIdent());

        ref.setRefValue(articuloDO);
    }

    public List<IVampiroArticuloDO> listByVampiroId(int vampiroId) throws SQLException {
        StringBuffer strbuf = new StringBuffer();

        strbuf.append("SELECT * FROM ");
        strbuf.append(getTableName());

        strbuf.append(" WHERE ");
        strbuf.append(VampiroArticuloDO.VAMPIRO_ID);
        strbuf.append(" = ");
        strbuf.append(vampiroId);

        System.err.println(strbuf.toString());

        ResultSet rs = //
        connection.createStatement().executeQuery(strbuf.toString());

        List<IVampiroArticuloDO> ret = new ArrayList<IVampiroArticuloDO>();

        while (rs.next()) {
            ret.add(resultSetToDO(rs));
        }

        return ret;
    }

    public List<IVampiroArticuloDO> listByArticuloId(int articuloId) throws SQLException {
        StringBuffer strbuf = new StringBuffer();

        strbuf.append("SELECT * FROM ");
        strbuf.append(getTableName());

        strbuf.append(" WHERE ");
        strbuf.append(VampiroArticuloDO.ARTICULO_ID);
        strbuf.append(" = ");
        strbuf.append(articuloId);

        System.err.println(strbuf.toString());

        ResultSet rs = //
        connection.createStatement().executeQuery(strbuf.toString());

        List<IVampiroArticuloDO> ret = new ArrayList<IVampiroArticuloDO>();

        while (rs.next()) {
            ret.add(resultSetToDO(rs));
        }

        return ret;
    }

    @Override
    public IVampiroArticuloDO loadByVampiroIdArticuloId(int vampiroId, int articuloId) throws SQLException {
        StringBuffer strbuf = new StringBuffer();

        strbuf.append("SELECT * FROM ");
        strbuf.append(getTableName());

        strbuf.append(" WHERE ");
        strbuf.append(VampiroArticuloDO.ARTICULO_ID);
        strbuf.append(" = ");
        strbuf.append(articuloId);
        strbuf.append(" AND ");
        strbuf.append(VampiroArticuloDO.VAMPIRO_ID);
        strbuf.append(" = ");
        strbuf.append(vampiroId);

        System.err.println(strbuf.toString());

        ResultSet rs = //
        connection.createStatement().executeQuery(strbuf.toString());

        if(rs.next()) {
            return resultSetToDO(rs);
        }

        return null;
    }
}
